//package edu.siu.math.egut.io;
//
//
//import java.io.BufferedInputStream;
//import java.io.BufferedOutputStream;
//import java.io.FileInputStream;
//import java.io.FileOutputStream;
//import java.io.IOException;
//import java.io.InputStream;
//import java.io.ObjectInput;
//import java.io.ObjectInputStream;
//import java.io.ObjectOutput;
//import java.io.ObjectOutputStream;
//import java.io.OutputStream;
//import java.io.Serializable;
//import java.util.ArrayList;
//import java.util.HashMap;
//import java.util.List;
//import java.util.Map;
//
//import org.apache.commons.collections15.list.TreeList;
//
//
//import edu.siu.math.egut.util.*;
//
//
///**
// * A serializable data structure for more complicated applications.
// * See, for example, SectionIntegral.
// * 
// * TODO make it impossible to write a Piece to one of the Group filenames.
// * 
// * @author Joe Pleso
// * @author Joseph Hundley
// * 
// *
// */
//public class SectionIntegralPiece implements Serializable{
//
//    public void setLeftInv(int[][] leftInv) {
//        this.leftInv = leftInv;
//    }
//    public void setUnip(Unipotent u) {
//        this.u = u;
//    }
//    public void setPoly(Polynomial p) {
//        this.p = p;
//    }
//    public void setTorusPart(Toral torusPart) {
//        this.torusPart = torusPart;
//    }
//    public void setTorusPart(int i , Polynomial p) {
//        this.torusPart.set(i, new RationalFunction(p));
//    }
//    public void setTorusPart(int i , RationalFunction r) {
//        this.torusPart.set(i, r);
//    }
//    public void setJacobian(Polynomial jacobian) {
//        this.jacobian = jacobian;
//    }
//    public void setDomain(Map<Polynomial, String> domain) {
//        this.domain = domain;
//    }
//    public int[][] getLeftInv() {
//        return leftInv;
//    }
//    public Unipotent getUnip() {
//        return u;
//    }
//    public Polynomial getPoly() {
//        return p;
//    }
//    public Toral getTorusPart() {
//        return torusPart;
//    }
//    public RationalFunction getTorusPart(int i ) {
//        return torusPart.get(i);
//    }
//    public Polynomial getJacobian() {
//        return jacobian;
//    }
//    public Map<Polynomial, String> getDomain() {
//        return domain;
//    }
//
//
//    /**
//     * 
//     */
//    private static final long serialVersionUID = 81L;
//    private int[][] leftInv; 
//    private Unipotent u;
//    private Polynomial p;
//    private Toral torusPart;
//    private Polynomial jacobian;
//    private Map<Polynomial, String> domain;
//    /**
//     * @param leftInv  an int[][] which should represent a list of  roots in one of the exceptional groups
//     * @param rightInv an int[][] which should represent a list of  roots in one of the exceptional groups
//     * @param URoots an int[][] which should represent a list of  roots in one of the exceptional groups which  is closed 
//     * under sums and can be conjugated to a set of positive roots.  (I.e, which defines a unipotent subgroup.)
//     * @param p  a polynomial
//     */
//    public SectionIntegralPiece(
//	    int[][] leftInv,
//    Unipotent u,
//    Polynomial p){
//	this.leftInv = leftInv;
//	    this.u = u;
//	    this.p = p;
//	    this.jacobian = Polynomial.create(1);
//	    RationalFunction[] preToral = new RationalFunction[u.getGroup().getRank()];
//	    for(int i = 0 ; i < preToral.length; i++)
//		preToral[i] = new RationalFunction(1);
//	    this.torusPart = new Toral(preToral);
//	    domain = new HashMap<Polynomial, String>();
//    }
//    public SectionIntegralPiece(
//	    int[][] leftInv,Unipotent u,
//    Polynomial p, Toral torusPart, Polynomial jacobian){
//	this.leftInv = leftInv;
//	    this.u = u;
//	    this.p = p;
//	    this.jacobian = jacobian;
//	    this.torusPart = torusPart;
//	    domain = new HashMap<Polynomial, String>();
//	    	    
//    }
//    public SectionIntegralPiece(
//	    int[][] leftInv,
//    Unipotent u,
//    Polynomial p, Toral torusPart, Polynomial jacobian, 
//    Map<Polynomial, String> domain){
//	this.leftInv = leftInv;
//	    this.u = u;
//	    this.p = p;
//	    this.jacobian = jacobian;
//	    this.torusPart = torusPart;
//	    this.domain = domain;
//	    	    
//    }
//    
//   public static void savePiece (String filename, SectionIntegralPiece p){
//        
//        try{
//              //use buffering
//              OutputStream file = new FileOutputStream( filename);
//              OutputStream buffer = new BufferedOutputStream( file );
//              ObjectOutput output = new ObjectOutputStream( buffer );
//              try{
//                output.writeObject(p);
//              }
//              finally{
//                output.close();
//              }
//            }  
//            catch(IOException ex){
//              System.err.println(ex);
//            }
//        
//    }
//   
//    
//    
//    public static SectionIntegralPiece loadPiece (String filename){
//        
//        
//        try{
//          //use buffering
//          InputStream file = new FileInputStream( filename );
//          InputStream buffer = new BufferedInputStream( file );
//          ObjectInput input = new ObjectInputStream ( buffer );
//          try{
//            //deserialize the List
//            SectionIntegralPiece answer =  (SectionIntegralPiece)input.readObject();
//            /* ISSUE:  answer will contain Monomials, Polynomials
//             * etc., which have not been entered into the 
//             * stores for these objects.
//             * 
//             */
//            answer = update( answer);
//           
//            return answer;
//          }
//          finally{
//            input.close();
//          }
//        }
//        catch(ClassNotFoundException ex){
//          System.err.println(ex);
//        }
//        catch(IOException ex){
//            System.err.println(ex);
//        }
//    
//
//        
//        return null;
//    
//    
//}
//
//    private static  SectionIntegralPiece update(SectionIntegralPiece p) {
//	return new SectionIntegralPiece( p.leftInv, p.u.update(), Polynomial.update(p.p), Toral.update(p.torusPart), Polynomial.update(p.jacobian), update(p.domain));
//
//    }
//    private static Map<Polynomial, String> update(Map<Polynomial, String> d) {
//	Map<Polynomial, String> answer = d;
//	for( Polynomial p: d.keySet()){
//	    answer.remove(p);
//	    answer.put(Polynomial.update(p), d.get(p));
//	}
//	
//	return answer;
//    }
//    public  String toTex(){
//	StringBuffer sb = new StringBuffer("$$\\int ");
//	sb.append(jacobian.toString());
//	sb.append("\\cdot f(");
//	sb.append(torusPart.toString());// TODO add toTeXString method to class
//	sb.append(u.toString());// TODO add toTeXString method to class Unipotent 
//	sb.append(")");
//	sb.append("\\cdot \\psi(");
//	sb.append(p);
//	sb.append(")\\; d(\\dots)$$\nDomain: \\begin{eqnarray*}");//TODO:  fix this to better address unconstrained case
//	for(Polynomial p: domain.keySet()){
//	    sb.append(p+"&&"+domain.get(p)+"\\\\");
//	    
//	}
//	    
//	sb.append("\\end{eqnarray*}");
//	
//	
//	return sb.toString();
//	
//    }
//    
//    
//    /**
//     * Checks polynomial, unipotent, tours, jacobian and domain for dependence on a given variable.
//     * @param variable the string name of a variable
//     * @return false, if the variable appears in the Piece, true otherwise.
//    */
//    public boolean isIndependentOf(final String variable){
//	if(! p.isIndependentOf(variable))
//	    return false;
//	for( Sunipotent s: u.getTerms())
//	    if(!s.getArgument().isIndependentOf(variable))
//		return false;
//	for( Polynomial p: domain.keySet())
//	    if(!p.isIndependentOf(variable))
//		return false;
//	for(int i = 1; i< torusPart.length(); i++)
//	    if(!torusPart.get(i).isIndependentOf(variable))
//		return false;
//	if(!jacobian.isIndependentOf(variable))
//	    return false;
//		
//	
//	return true;
//    }
//    public void simplify() {
///*	List<int[]> goodPsi = getGoodPsi();
//	List<int[]> badPsi = Algorithms.getBadPsi(p);
//	for(int i =  u.getNumberOfTerms()-1; i>=0; i--){
//	    if(u.stringOf(u.get(i))!= null){
//		List<int[]> rootsToTry = Algorithms.getRootsToTry(u.get(i).getRoot(), goodPsi, badPsi, leftInv);
//		for( int[] a : rootsToTry ){
//		    tryKill(a);
//		}
//	    }
//	}
//	
//
//	
//  */  }  // end Simplify
//    
//    public  List<int[]> getGoodPsi() {
//	    List<int[]> answer = new TreeList<int[]>();
//	    // FIXME finish.
//	    return answer;
//
//	
//    }
//    
//    public void actBy(int weylAsInt) throws BadSubstitutionException{
//	// act on the torus part
//	torusPart = torusPart.imageUnder(weylAsInt);
//	
//	// compile a list of sunis appearing in u with default arg.
///*	List<Sunipotent> defaultArg = new ArrayList<Sunipotent>();
//	for(int i = 0; i < u.getNumberOfTerms(); i++)
//	    if( i == u.getIndex(u.get(i)))
//		if(u.get(i).hasDefaultArg())
//		    defaultArg.add(u.get(i));
//*/	    
//	// act on u.
//	u.actBy(weylAsInt);
//	p= u.chOfVars(p);
//	// make changes of variable so that x_a( u_a) becomes
//	// x_b(u_b), not x_b( u_a).  do in stages, in case variable 
///*	TODO come up with a good approach to that issue.  (the 
// * originally-envisioned one is flawed because the question of whether
// * u_b is in use, and what to do if it is, is a kind of thorny one.
// * 
// *      for( int i = 0 ; i < defaultArg.size(); i++){
//	    this.chOfVar(defaultArg.get(i).defaultArg().getVar(), 
//		    defaultArg.get(i).imageUnder(weylAsInt).placeHolder());
//	}
//*/	
//	leftInv = u.getGroup().weylAction(weylAsInt, leftInv);
//	
//	    
//	/* TODO
//	 * (1)make changes of variable so that default args become new
//	 * default...
//	 * (2) change leftInv
//	 */
//	
//	
//    }
//    public void chOfVar(String var, Polynomial sub) throws BadSubstitutionException{
//	u.replace(var, sub);
//	p.replace(var, sub);
//	//TorusPart
//	//Jacobian
//	//Domain
//	
//    }
//    
//    
//    
//}
